package com.swn.common.util;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Locale;

/**
 * 将查询出来的结果ResultSet转化为单个的实体对象
 */
public class RecordToBeanUtil {

	/**
	 * 
		 * 功能说明:<将查询出来的结果ResultSet转化为单个的实体对象 > <br>
		 * 创建人： yanliangliang <br>
		 * 创建时间：2016-5-11 上午9:25:44  <br>
		 * @param @param rs  单个的实体对象的.class
		 * @param @param classbean  单个的实体对象的.class
		 * @example list = this.getJdbcTemplate().query(pageSql, new
		 *          RowMapper<TestDataVO>() { public TestDataVO mapRow(ResultSet rs,
		 *          int rowNum) throws SQLException { TestDataVO TestDataVO = new
		 *          TestDataVO(); TestDataVO
		 *          =(TestDataVO)RecordToBeanUtil.recordToBean(rs,TestDataVO.class);
		 *          return TestDataVO; } });
		 * @return Object   单个的实体对象
	 */
	@SuppressWarnings("rawtypes")
	public static Object recordToBean(ResultSet rs, Class classbean) {
		if (classbean != null && rs != null) {
			try {
				Object obj = classbean.newInstance();
				Method[] m = classbean.getMethods();// 获取实体对象的所有方法
				String methodName = new String();
				ResultSetMetaData rsmd = rs.getMetaData();
				int columCount = rsmd.getColumnCount();// 获取结果集合的列的个数
				for (int i = 0; i < columCount; i++) {// 遍历各个列
					String key = rsmd.getColumnName(i + 1);// 获取列名，列名从1开始
					String ColumnTypeName = rsmd.getColumnTypeName(i + 1);// 获取列的数据类型
					// 将列名转化为setXXXX形式
					String[] keyArr = key.split("_");
					for (int j = 0; j < keyArr.length; j++) {
						if (j == 0) {
							if (keyArr[j].length() > 1) {
								methodName = "set"
										+ keyArr[j].substring(0, 1)
										+ keyArr[j].substring(1).toLowerCase(
												Locale.ENGLISH);
							} else if (keyArr[j].length() == 1) {
								methodName = "set" + keyArr[j].substring(0, 1);
							}
						} else {
							if (keyArr[j].length() > 1) {
								methodName = methodName
										+ keyArr[j].substring(0, 1)
										+ keyArr[j].substring(1).toLowerCase(
												Locale.ENGLISH);
							} else if (keyArr[j].length() == 1) {
								methodName = methodName
										+ keyArr[j].substring(0, 1);
							}
						}
					}
				
					// 对应实体类的方法，封装实体类数据
					for (Method method : m) {
						if (method.getName().endsWith(methodName)) {
							if ("VARCHAR2".equals(ColumnTypeName)) {
								
								method.invoke(obj,
										new Object[] { rs.getString(key) });
							} else if ("NUMBER".equals(ColumnTypeName)) {
								
								if (rsmd.getScale(i + 1) > 0) {
									method.invoke(obj, new Object[] { rs
											.getBigDecimal(key) });
								} else {
									method.invoke(obj,
											new Object[] { rs.getInt(key) });
								}
							}else if ("CHAR".equals(ColumnTypeName)) {
							
								method.invoke(obj,
										new Object[] { rs.getString(key) });
							}
							break;
						}
					}
				}
				return obj;

			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
		return null;
	}

	/**
	 * <p>
	 * 功能说明:<根据实体类获取该实体类对应的数据库的表字段>
	 * <p>
	 * 创建人： yanliangliang
	 * <p>
	 * 创建时间：2016-4-15 下午3:04:18
	 * <p>
	 * @param classbean 注意classBean必须为PO，即类的所有属性都是持久化的
	 * <p>
	 * 返回类型：String 大写的字段字符串，用"，"隔开，例如：ID, SORG_ID, TASK_CODE, SORG_TYPE
	 * <p>
	 * 异常：@throws
	 */
	@SuppressWarnings("rawtypes")
	public static String getTableColnames(Class classbean) {
		StringBuffer sbf = new StringBuffer(" ");
		Field[] m = classbean.getDeclaredFields();// 获取类的所有属性

		for (int i = 0; i < m.length; i++) {
			Field f = m[i];
			String[] ss = f.getName().split("(?<!^)(?=[A-Z])");// 将属性存在用大写字符分割为数组
			StringBuffer colname = new StringBuffer();
			for (int j = 0; j < ss.length; j++) {
				colname.append(ss[j]);
				if (j != ss.length - 1) {
					colname.append("_");// 在属性大写字母前增加_
				}
			}
			sbf.append(colname);
			if (i != m.length - 1) {
				sbf.append(", ");
			}
		}

		return sbf.toString().toUpperCase();// 转成大写
	}

	/**
	 * <p>
	 * 功能说明:<根据实体类获取该实体类对应的数据库的表字段的个数>
	 * <p>
	 * 创建人： yanliangliang
	 * <p>
	 * 创建时间：2016-4-15 下午3:04:18
	 * <p>
	 * @param classbean注意classbean必须为PO，即类的所有属性都是持久化的
	 * <p>
	 * 返回类型：String 例如："?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?";
	 * <p>
	 * 异常：@throws
	 */
	@SuppressWarnings("rawtypes")
	public static String getTableColNumber(Class classbean) {
		StringBuffer sbf = new StringBuffer();
		Field[] m = classbean.getDeclaredFields();// 获取类的所有属性

		for (int i = 0; i < m.length; i++) {
			sbf.append("?");
			if (i != m.length - 1) {
				sbf.append(", ");
			}
		}

		return sbf.toString();
	}

	/**
	 * <p>
	 * 功能说明:<根据实体类获取该实体类对应的数据库的表字段的set方法>
	 * <p>
	 * 创建人： yanliangliang
	 * <p>
	 * 创建时间：2016-4-15 下午3:04:18
	 * <p>
	 * @param classbean 注意classbean必须为PO，即类的所有属性都是持久化的
	 * <p>
	 * 返回类型：String 例如：
	 * " SET  BORG_LEVEL=? , BORG_TYPE=? ,IF_HIS=? , IF_SORG_PARTY=? WHERE "
	 * <p>
	 * 异常：@throws
	 */
	@SuppressWarnings("rawtypes")
	public static String getTableColSet(Class classbean) {
		StringBuffer sbf = new StringBuffer(" SET ");
		Field[] m = classbean.getDeclaredFields();// 获取类的所有属性

		for (int i = 1; i < m.length; i++) {// ！！！注意默认是第0个属性为主键
			Field f = m[i];
			String[] ss = f.getName().split("(?<!^)(?=[A-Z])");// 将属性存在用大写字符分割为数组
			StringBuffer colname = new StringBuffer();
			for (int j = 0; j < ss.length; j++) {
				colname.append(ss[j]);
				if (j != ss.length - 1) {
					colname.append("_");// 在属性大写字母前增加_
				}
			}
			sbf.append(colname);
			sbf.append("=? ");
			if (i != m.length - 1) {
				sbf.append(", ");
			}
		}
		sbf.append(" where ");

		return sbf.toString().toUpperCase();// 转成大写
	}

	/**
	 * <p>
	 * 功能说明:save方法为PreparedStatement传参数
	 * <p>
	 * 创建人： yanliangliang
	 * 创建时间：2016-4-15 下午3:44:55
	 * @param ps PreparedStatement
	 * @param classbean 注意classbean必须为PO，即类的所有属性都是持久化的
	 * 返回类型：PreparedStatement 	主键是第一个参数
	 * 
	 */
	@SuppressWarnings("rawtypes")
	public static PreparedStatement fillTablePS(PreparedStatement ps ,Object obj) {
		 Field[] m = obj.getClass().getDeclaredFields();//获得属性
		Class clazz = obj.getClass();
		PropertyDescriptor pd;
		for (int i = 0; i < m.length; i++) {// ！！！注意默认是第0个属性为主键
			try {
				Field f = m[i];
				String type = f.getType().getName();
				pd = new PropertyDescriptor(f.getName(), clazz);
				Method getMethod = pd.getReadMethod();// 获得get方法
				Object o = getMethod.invoke(obj);
				 if(type.equals("java.lang.String")){
					 ps.setString(i+1, (String) o);
				 }else if(type.equals("java.lang.Integer")){
					 ps.setInt(i+1, (Integer) (o==null?0:o));
				 }else if(type.equals("java.math.BigDecimal")){
					 ps.setBigDecimal(i+1, (BigDecimal) o);
				 }
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			} catch (IntrospectionException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		return ps;
	}
	/**
	 * <p>
	 * 功能说明:update方法为PreparedStatement传参数<p>
	 * 创建人： yanliangliang
	 * 创建时间：2016-4-15 下午3:44:55
	 * @param ps PreparedStatement
	 * @param classbean 注意classbean必须为PO，即类的所有属性都是持久化的
	 * <p>
	 * 返回类型：PreparedStatement 	主键是最后一个参数
	 * 
	 */
	@SuppressWarnings("rawtypes")
	public static PreparedStatement fillTablePSForUpdate(PreparedStatement ps ,Object obj) {
		 Field[] m = obj.getClass().getDeclaredFields();//获得属性
		Class clazz = obj.getClass();
		try {
			for (int i = 0; i < m.length; i++) {// ！！！注意默认是第0个属性为主键
				Field f = m[i];
				String type = f.getType().getName();
				Object o = new PropertyDescriptor(f.getName(), clazz).getReadMethod().invoke(obj);
				if(i == 0){//第一个是主键，参数放到最后面
					 if(type.equals("java.lang.String")){
							ps.setString(m.length, (String) o);
					 }else if(type.equals("java.lang.Integer")){
						 ps.setInt(m.length, (Integer) o);
					 }else if(type.equals("java.math.BigDecimal")){
						 ps.setBigDecimal(m.length, (BigDecimal) o);
					 }
				}else{
					 if(type.equals("java.lang.String")){
							ps.setString(i, (String) o);
					 }else if(type.equals("java.lang.Integer")){
						 ps.setInt(i, (Integer) o);
					 }else if(type.equals("java.math.BigDecimal")){
						 ps.setBigDecimal(i, (BigDecimal) o);
					 }
				}
			}
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (IntrospectionException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return ps;
	}
	/**
	 * <p>
	 * 功能说明:saveEntity获取类的Object[]
	 * <p>
	 * 创建人： yanliangliang
	 * 创建时间：2016-4-15 下午3:44:55
	 * @param ps PreparedStatement
	 * @param classbean 注意classbean必须为PO，即类的所有属性都是持久化的
	 * <p>
	 * 返回类型：Object[] 	主键是第一个参数
	 * 
	 */
	@SuppressWarnings("rawtypes")
	public static Object[] getBeanValues(Object obj) {
		
		Field[] m = obj.getClass().getDeclaredFields();//获得属性
		Object[] objs = new Object[m.length];
		Class clazz = obj.getClass();
		PropertyDescriptor pd;
		for (int i = 0; i < m.length; i++) {// ！！！注意默认是第0个属性为主键
			try {
				Field f = m[i];
				pd = new PropertyDescriptor(f.getName(), clazz);
				Method getMethod = pd.getReadMethod();// 获得get方法
				Object o = getMethod.invoke(obj);
				objs[i]=o;
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			} catch (IntrospectionException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}

		return objs;
	}
	/**
	 * 功能说明:updateEntity获取类的Object[]
	 * <p>
	 * 创建人： yanliangliang  
	 * 创建时间：2016-4-15 下午3:44:55
	 * @param ps PreparedStatement
	 * @param classbean 注意classbean必须为PO，即类的所有属性都是持久化的
	 * <p>
	 * 返回类型：Object[] 	主键是最后一个参数
	 * 
	 */
	@SuppressWarnings("rawtypes")
	public static Object[] getBeanValuesForUpdate(Object obj) {
		Field[] m = obj.getClass().getDeclaredFields();//获得属性
		Class clazz = obj.getClass();
		Object[] objs = new Object[m.length];
		try {
			for (int i = 0; i < m.length; i++) {// ！！！注意默认是第0个属性为主键
					Field f = m[i];
					Object o = new PropertyDescriptor(f.getName(), clazz).getReadMethod().invoke(obj);
					if(i==0){
						objs[m.length-1] = o;
					}else{
						objs[i] = o;
					}
			}
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (IntrospectionException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		

		return objs;
	}
	
	
}
